package com.duoec.magichour.service.impl;

import com.duoec.magichour.core.exceptions.BusinessException;
import com.duoec.magichour.core.utils.MD5Utils;
import com.duoec.magichour.dto.BaseResponse;
import com.duoec.magichour.dto.UserInfo;
import com.duoec.magichour.dto.request.UserLoginWithCodeDto;
import com.duoec.magichour.dto.request.UserLoginWithPwdDto;
import com.duoec.magichour.dto.request.UserQuery;
import com.duoec.magichour.dto.request.UserRegistSave;
import com.duoec.magichour.dto.response.UserDetailDto;
import com.duoec.magichour.dto.response.UserSimpleInfoDto;
import com.duoec.magichour.enums.SmsMessageTypeEnum;
import com.duoec.magichour.mapper.UserMapper;
import com.duoec.magichour.pojo.Authorize;
import com.duoec.magichour.pojo.Sms;
import com.duoec.magichour.pojo.User;
import com.duoec.magichour.service.AuthorizeService;
import com.duoec.magichour.service.SmsService;
import com.duoec.magichour.service.UserFollowService;
import com.duoec.magichour.service.UserService;
import com.google.common.base.Strings;
import com.google.common.collect.Maps;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;
import java.util.Random;

/**
 * Created by ycoe on 17/6/25.
 */
@Service
public class UserServiceImpl implements UserService {
    @Value("${user.pwd.salt}")
    private String salt;

    @Value("${user.nickname.default}")
    private String defaultNickname;

    @Value("${sms.code.maxErrorCount}")
    private int codeMaxErrorCount;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private UserFollowService userFollowService;

    @Autowired
    private AuthorizeService authorizeService;

    @Autowired
    private SmsService smsService;

    @Override
    public UserSimpleInfoDto regist(UserRegistSave request) {
        User user = new User();
        String mobile = request.getMobile();
        user.setMobile(mobile);
        user.setPwd(getPassword(request.getPassword()));
        String nickname = request.getNickname();
        if (Strings.isNullOrEmpty(nickname)) {
            user.setNickname(getNicknameFromMobile(mobile));
        } else {
            user.setNickname(nickname);
        }

        userMapper.insertSelective(user);

        UserSimpleInfoDto usi = new UserSimpleInfoDto();
        BeanUtils.copyProperties(user, usi);
        return usi;
    }

    @Override
    public Authorize loginWithPwd(UserLoginWithPwdDto request) {
        String mobile = request.getMobile();
        User user = userMapper.getByMobile(mobile);
        if (user == null) {
            throw new BusinessException(BaseResponse.CODE_NOT_FIND, "用户不存在！");
        }
        if (!user.getPwd().equals(getPassword(request.getPassword()))) {
            throw new BusinessException(BaseResponse.CODE_PARAM_INVALID, "密码错误！");
        }

        //登录成功
        Authorize authorize = doLogin(user);
        return authorize;
    }

    @Override
    public Authorize loginWithCode(UserLoginWithCodeDto request) {
        String mobile = request.getMobile();
        User user = userMapper.getByMobile(mobile);
        if (user == null) {
            throw new BusinessException(BaseResponse.CODE_NOT_FIND, "用户不存在！");
        }

        Sms sms = smsService.getByMobileType(mobile, SmsMessageTypeEnum.MOBILE_CODE);
        if (sms == null) {
            throw new BusinessException(BaseResponse.CODE_PARAM_INVALID, "验证码已失效请重新获取！");
        }

        if (sms.getErrorCount() >= codeMaxErrorCount) {
            //验证码错误次数过多
            throw new BusinessException(BaseResponse.CODE_PARAM_INVALID, "验证码错误次数过多，请稍候再试！");
        }

        if (!request.getCode().equals(sms.getCode())) {
            //写错误次数
            smsService.incErrorCount(sms.getId());
            throw new BusinessException(BaseResponse.CODE_PARAM_INVALID, "验证码错误！");
        }

        //将短信验证码设置为已用
        smsService.used(sms.getId());

        //登录成功
        Authorize authorize = doLogin(user);
        return authorize;
    }

    @Override
    public void logout(UserInfo userInfo) {
        authorizeService.logout(userInfo);
    }

    @Transactional
    @Override
    public String resetMobilePwd(String mobile) {
        Sms sms = smsService.getByMobileType(mobile, SmsMessageTypeEnum.RESET_PWD);
        String pwd;
        if (sms == null) {
            //需要重置密码
            pwd = genPwd();

            User user = userMapper.getByMobile(mobile);
            String password = getPassword(pwd);
            if (user != null) {
                //用户已存在，直接重置密码

                //检查用户是否允许重置密码

                userMapper.updatePwd(user.getId(), password);
            } else {
                //用户不存在，则新添加一个用户
                user = new User();
                user.setMobile(mobile);
                user.setNickname(getNicknameFromMobile(mobile));
                user.setPwd(password);
                userMapper.insertSelective(user);
            }
        } else {
            pwd = sms.getCode();
        }

        return smsService.resetMobilePwd(mobile, pwd);
    }

    @Override
    public List<User> query(UserQuery userQuery) {
        return null;
    }

    @Override
    public Map<Long, UserSimpleInfoDto> getUserSimpleInfoMap(List<Long> userIdList) {
        Map<Long, UserSimpleInfoDto> userSimpleInfoMap = Maps.newHashMap();
        if (userIdList == null || userIdList.isEmpty()) {
            return userSimpleInfoMap;
        }

        List<UserSimpleInfoDto> userSimpleInfoList = userMapper.getUserSimpleInfoByIds(userIdList);
        if (userSimpleInfoList != null) {
            userSimpleInfoList.forEach(userInfo -> userSimpleInfoMap.put(userInfo.getId(), userInfo));
        }
        return userSimpleInfoMap;
    }

    @Override
    public User getUser(Long userId) {
        return userMapper.selectByPrimaryKey(userId);
    }

    @Override
    public UserSimpleInfoDto getUserSimpleInfo(Long userId) {
        User user = userMapper.selectByPrimaryKey(userId);
        UserSimpleInfoDto usi = new UserSimpleInfoDto();
        BeanUtils.copyProperties(user, usi);
        return usi;
    }

    @Override
    public void incFavoriteArticle(Long userId) {
        userMapper.incFavoriteArticle(userId);
    }

    @Override
    public void incFollowArticle(Long authorId) {
        userMapper.incFollowArticle(authorId);
    }

    @Override
    public void incArticleCount(Long userId) {
        userMapper.incArticleCount(userId);
    }

    @Override
    public void incFavoriteUserCount(long userId) {
        userMapper.incFavoriteUserCount(userId);
    }

    @Override
    public void incFansCount(long userId) {
        userMapper.incFansCount(userId);
    }

    @Override
    public UserDetailDto getDetail(UserInfo userInfo, Long userId) {
        User user = userMapper.selectByPrimaryKey(userId);
        if (user == null) {
            throw new BusinessException(BaseResponse.CODE_NOT_FIND, "用户不存在！");
        }
        UserDetailDto detail = new UserDetailDto();
        BeanUtils.copyProperties(user, detail);

        if (userInfo != null && !userInfo.getId().equals(userId)) {
            //检查当前用户是否关注过{userId}
            boolean isFollow = userFollowService.isFollow(userInfo.getId(), userId);
            detail.setFollow(isFollow);
        }
        return detail;
    }

    private String genPwd() {
        return String.valueOf(100000 + new Random().nextInt(899999));
    }

    private Authorize doLogin(User user) {
        return authorizeService.mobilePwdLogin(user);
    }

    private String getNicknameFromMobile(String mobile) {
        int length = mobile.length();
        return defaultNickname + mobile.substring(length - 4, length);
    }

    private String getPassword(String pwd) {
        return MD5Utils.md5(pwd + salt);
    }
}
